using System;
using System.Collections;
using System.ComponentModel;
using System.Data;

using Gtk;
using System.Drawing;

namespace NPlot { namespace Gtk {

	public class PlotSurface2D : DrawingArea, IPlotSurface2D {
		NPlot.PlotSurface2D ps;
		/*Axis xAxis1Cache;
		Axis yAxis1Cache;
		Axis xAxis2Cache;
		Axis yAxis2Cache;*/

		// The cache.
		System.Drawing.Bitmap bitmap_cache;
		Gdk.Rectangle current_allocation;	// The current allocation. 
		bool allocated = false;

		public PlotSurface2D (IntPtr x) : base (x)
		{
		Console.WriteLine (Environment.StackTrace);	
		}

		public PlotSurface2D ()
		{
			ps = new NPlot.PlotSurface2D ();
			CanFocus = false;
			SetSizeRequest (200, 200);
		}

		public void Refresh ()
		{
			UpdateCache ();
			QueueDrawArea (0, 0, Allocation.Width, Allocation.Height);
		}
		
		protected override bool OnExposeEvent (Gdk.EventExpose args)
		{
			Gdk.Rectangle area = args.Area;

			Console.WriteLine (area);
			using (Graphics g = Gdk.Graphics.FromDrawable (args.Window)){
				Rectangle bounds = new Rectangle (area.X, area.Y, area.Width, area.Height);
				
				g.DrawImage (bitmap_cache, bounds, bounds, GraphicsUnit.Pixel);
			}
			return true;
		}

		protected override void OnSizeAllocated (Gdk.Rectangle allocation)
		{
			allocated = true;
			current_allocation = allocation;
			UpdateCache ();
			base.OnSizeAllocated (allocation);
		}

		void UpdateCache ()
		{
			if (!allocated)
				return;
			
			if (bitmap_cache != null)
				bitmap_cache.Dispose ();
			
			bitmap_cache = new System.Drawing.Bitmap (current_allocation.Width, current_allocation.Height);
			using (Graphics g = Graphics.FromImage (bitmap_cache)){
				Rectangle bounds = new Rectangle (
					0, 0, current_allocation.Width, current_allocation.Height);
				ps.Draw (g, bounds);
			}
		}

#region IPlotSurface2D interface implementation
	
		public void Add (IDrawable p, int zOrder)
		{
			ps.Add (p, zOrder);
		}

		public void Add (IDrawable p)
		{
			ps.Add (p);
		}
		

		public void Add (IDrawable p, NPlot.PlotSurface2D.XAxisPosition xp, NPlot.PlotSurface2D.YAxisPosition yp)
		{
			ps.Add (p, xp, yp);
		}

		public void Add (NPlot.IDrawable p, NPlot.PlotSurface2D.XAxisPosition xp, NPlot.PlotSurface2D.YAxisPosition yp, int zOrder)
		{
			ps.Add (p, xp, yp, zOrder);
		}
		
		public void Clear()
		{
			ps.Clear ();
		}

		public NPlot.Legend Legend {
			get {
				return ps.Legend;
			}
			
			set {
				ps.Legend = value;
			}
		}

		public int Padding {
			get {
				return ps.Padding;
			}

			set {
				ps.Padding = value;
			}
		}

		public int LegendZOrder {
			get {
				return ps.LegendZOrder;
			}

			set {
				ps.LegendZOrder = value;
			}
		}


		
		public System.Drawing.Color PlotBackColor {
			set {
				ps.PlotBackColor = value;
			}
		}
		
		public System.Drawing.Bitmap PlotBackImage
		{
			set {
				ps.PlotBackImage = value;
			}
		}

		public IRectangleBrush PlotBackBrush
		{
			set {
				ps.PlotBackBrush = value;
			}
		}

		public Color TitleColor
		{
			set
			{
				ps.TitleColor = value;
			}
		}

		public Brush TitleBrush
		{
			get
			{
				return ps.TitleBrush;
			}
			set
			{
				ps.TitleBrush = value;
			}
		}
		

		/// <summary>
		/// Gets an array list containing all drawables currently added to the PlotSurface2D.
		/// </summary>
		public ArrayList Drawables
		{
			get
			{
				return ps.Drawables;
			}
		}

		public void Remove (IDrawable p, bool updateAxes) 
		{
			ps.Remove(p, updateAxes);
		}
		
		public string Title {
			get {
				return ps.Title;
			}
			
			set {
				ps.Title = value;
			}
		}
		
		public System.Drawing.Font TitleFont {
			get {
				return ps.TitleFont;
			}

			set {
				ps.TitleFont = value;
			}
		}
				
		public System.Drawing.Drawing2D.SmoothingMode SmoothingMode {
			get {
				return ps.SmoothingMode;
			}
			set {
				ps.SmoothingMode = value;
			}
		}

		public void AddAxesConstraint (AxesConstraint c)
		{
				ps.AddAxesConstraint (c);
		}

		public Axis XAxis1 {
			get {
				return ps.XAxis1;
			}
			set
				{
					ps.XAxis1 = value;
				}
		}
		
		public Axis YAxis1 {
			get {
				return ps.YAxis1;
			}
			
			set {
				ps.YAxis1 = value;
			}
		}
			
		public Axis XAxis2 {
			get {
				return ps.XAxis2;
			}

			set {
				ps.XAxis2 = value;
			}
		}
		
		public Axis YAxis2 {
			get {
				return ps.YAxis2;
			}
			set {
				ps.YAxis2 = value;
			}
		}

		public bool AutoScaleTitle {
			get {
				return ps.AutoScaleTitle;
			}
			
			set {
				ps.AutoScaleTitle = value;
			}
		}

		public bool AutoScaleAutoGeneratedAxes {
			get {
				return ps.AutoScaleAutoGeneratedAxes;
			}
			
			set {
				ps.AutoScaleAutoGeneratedAxes = value;
			}
		}
		
		public System.Drawing.Bitmap Bitmap {
			get { return bitmap_cache;}
		}	  

		public int Width {
			get { return current_allocation.Width; }
		}

		public int Height {
			get { return current_allocation.Height;}
		}

#endregion
	
} }
}
